/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.pdx.cs.guavadata.domain;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.lang.String;
import java.math.BigDecimal;
import java.sql.ResultSet;

/**
 *
 * @author VuTran
 */
public class Decimal extends Domain {

    private BigDecimal min;
    private BigDecimal max;
    
    public BigDecimal getMax() {
        return max;
    }
    
    public void setMax(BigDecimal value) {
        max = value;
    }
    
    public BigDecimal getMin() {
        return min;
    }
    
    public void setMin(BigDecimal value) {
        min = value;
    }

    public Decimal() {
        this.min = null;
        this.max = null;
    }

    public Decimal(BigDecimal min, BigDecimal max) {
        this.min = min;
        this.max = max;
    }
    
    @Override
    public boolean validate(Object o) {
        BigDecimal i = null;
        
        if (o == null) return true;
        if (o instanceof BigDecimal) i = (BigDecimal) o;
       
        // If still null at this point, then o isn't a valid byte-worthy object
        if (i == null) return false;
        if ((min != null) && (min.compareTo(i) == 1)) return false;
        if ((max != null) && (max.compareTo(i) == -1)) return false;
        return true;
    }

    @Override
    public Object convertString(String s) throws DomainConversionException {
        if ((s == null) || (s == "")) return null;
        BigDecimal d;
        try {
            d = new BigDecimal(s);
        } catch (NumberFormatException e) {
            throw new DomainConversionException("Could not convert " + s + " into a decimal integer.");
        }
        
        if ((min != null) && (min.compareTo(d) == 1)) throw new DomainConversionException("Value " + s + " is too small for a domain with minimum value " + min.toString() + ".");
        if ((max != null) && (max.compareTo(d) == -1)) throw new DomainConversionException("Value " + s + " is too big for a domain with minimum value " + max.toString() + ".");
        return d;
    }

    @Override
    public Class getNaiveType() {
        return BigDecimal.class;
    }

    @Override
    public String getDBType() {
        return "decimal";
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Decimal)) return false;
        Decimal that = (Decimal) obj;
        return ((this.max.compareTo(that.max) == 0) && (this.min.compareTo(that.min) == 0));
    }

    @Override
    public int hashCode() {
        return Decimal.class.hashCode() * (min.hashCode() + 1) + max.hashCode();
    }

    @Override
    public String toString() {
        return "Numeric";
    }

    
    @Override
    public Domain upcast() {
        return null;
    }

    @Override
    public Object upcastValue(Object o) throws Exception {
        return null;
    }

    @Override
    public Domain merge(Domain d) {
        if (!(d instanceof Decimal)) return null;
        Decimal that = (Decimal) d;
        BigDecimal nmax = (this.max.compareTo(that.max) == 0) ? this.max : null;
        BigDecimal nmin = (this.min.compareTo(that.min) == 0) ? this.min : null;
        return new Decimal(nmin, nmax);
    }

    @Override
    public boolean isOrdered() {
        return true;
    }

    @Override
    public boolean canContain() {
        return false;
    }

    @Override
    public Domain clone() {
        return new Decimal(this.min, this.max);
    }

    @Override
    public Element ToXml(Document xdoc) {
        Element xe = xdoc.createElement("Domain");
        xe.setAttribute("Type", "Decimal");
        if (max != null) xe.setAttribute("MaxValue", max.toString());
        if (min != null) xe.setAttribute("MinValue", min.toString());
        return xe;
    }


    public static Decimal fromElement(Element e) {
        Decimal o = new Decimal();
        if (e.hasAttribute("MaxValue")) {
            o.max = new BigDecimal(e.getAttribute("MaxValue"));
        }
        if (e.hasAttribute("MinValue")) {
            o.min = new BigDecimal(e.getAttribute("MinValue"));
        }
        return o;
    }

    public static Decimal FromDBInfoRow(ResultSet dr) {
        Decimal o = new Decimal();
        return o;
    }
}
